#include <18f4550.h>
#include <stdlib.h>
//#fuses HSPLL,NOWDT,NOPROTECT,NOLVP
#fuses HS,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,NOVREGEN,NOSTVREN
#use   delay(clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7)
#priority rtcc

#byte PORTA=0xF80
#byte TRISA=0xF92
#byte PORTB=0xF81
#byte TRISB=0xF93
#bit RB0 = PORTB.0
#bit RB1 = PORTB.1
#bit RB2 = PORTB.2
#bit RB3 = PORTB.3
#bit RB4 = PORTB.4
#bit RB5 = PORTB.5
#bit RB6 = PORTB.6
#bit RB7 = PORTB.7
#bit RA0 = PORTA.0
#bit RA1 = PORTA.1
#bit RA2 = PORTA.2
#bit RA3 = PORTA.3
#bit TMR1IF=0xF9E.0
#bit TMR0IF=0xFF2.2
#byte INTCON=0xFF2
#byte TMR0L=0xFD6
#byte TMR0H=0xFD7
#byte TOSH=0x0FFE
#Byte TOSL=0x0FFD
#byte TOSU=0x0FFF
#byte PCL=0xFF9
#byte PCLATU=0XFFB
#byte PCLATH=0xFFA
#byte STKPTR=0xFFC
#byte STATUS=0xFD8
#byte BSR=0xFE0
#byte WREG=0xFE8
#byte Wtemp=0x04
#byte STATUStemp=0x05
#byte BSRtemp=0x06

struct pcb
{
   int id;
   unsigned int32 di;
   unsigned int32 da;
   int estado;
   unsigned int16 muestreo;
   unsigned int16 timer;
   int8 pila;
   int1 estadoc;
   int w;
   int status;
   int bsr;
};
struct pcb colart[6];
struct pcb cola[6];
struct pcb proceso[5]; 
int calendarizacion=1;
int i, j, m, mayor, ma;
char dato, buffer[10];
int np=0;
int cp=0;
int npc=0;
int c1=1, c2=1, c3=1, r=0, z;
int u1=1, u2=1, u3=1;
int y[3];
int1 minus[3];
float factor[3];
#ORG 0x1200,0x1350
void proceso1()
   {switch(c1) 
    {case 1: RB0=1;
            RB1=0;
            RB2=0;
            RB3=0;
            if(minus[0]){c1=4;}
            else {c1++;}
            break;
     case 2:RB0=0;
             RB1=1;
             RB2=0;
             RB3=0;
             if(minus[0]){c1--;}
             else {c1++;}
             break;
      case 3:RB0=0;
             RB1=0;
             RB2=1;
             RB3=0;
             if(minus[0]){c1--;}
             else {c1++;}
             break;
      case 4:RB0=0;
              RB1=0;
              RB2=0;
              RB3=1;
              if(minus[0]){c1--;}
              else {c1=1;}
              break;}
       
       u1++;
       cola[1].estado=0;
       np--;
       goto_address(proceso[0].di); 
   }
#ORG 0x1400,0x1550
void proceso2()
   {  
       switch(c2) 
    {case 1: RB4=1;
            RB5=0;
            RB6=0;
            RB7=0;
            if(minus[1]){c2=4;}
            else {c2++;}
            break;
     case 2:RB4=0;
             RB5=1;
             RB6=0;
             RB7=0;
             if(minus[1]){c2--;}
             else {c2++;}
             break;
      case 3:RB4=0;
             RB5=0;
             RB6=1;
             RB7=0;
             if(minus[1]){c2--;}
             else {c2++;}
             break;
      case 4:RB4=0;
              RB5=0;
              RB6=0;
              RB7=1;
              if(minus[1]){c2--;}
              else {c2=1;}
              break;}
       
       u2++;
       cola[1].estado=0;
       np--;
       goto_address(proceso[0].di); 
   }
#ORG 0x1600,0x1750
void proceso3()
   {
       switch(c3) 
    {case 1: RA0=1;
            RA1=0;
            RA2=0;
            RA3=0;
            if(minus[2]){c3=4;}
            else {c3++;}
            break;
     case 2:RA0=0;
             RA1=1;
             RA2=0;
             RA3=0;
             if(minus[2]){c3--;}
             else {c3++;}
             break;
      case 3:RA0=0;
             RA1=0;
             RA2=1;
             RA3=0;
             if(minus[2]){c3--;}
             else {c3++;}
             break;
      case 4:RA0=0;
              RA1=0;
              RA2=0;
              RA3=1;
              if(minus[2]){c3--;}
              else {c3=1;}
              break;}
      
       u3++;
       cola[1].estado=0;
       np--;
       goto_address(proceso[0].di); 
   }
#ORG 0x1800,0x1D00
void proceso4()
   { 
   RB3=~RB3;
   cola[1].estado=0;  //se pone a cero para que no vuelva a ejecutarse
   np--;
   goto_address(proceso[0].di); 
   
       }
#INT_TIMER1
void TIMER1_isr() {
   ///////////////////////GUARDANDO VALORES DEL PROCESO/////////////////////////
   if(np>0){
   cola[1].w=Wtemp;
   cola[1].status=STATUStemp;
   cola[1].bsr=BSRtemp;
   cola[1].da=make32(TOSU,TOSH,TOSL);
   STKPTR--; 
   cola[1].pila=STKPTR;
   /////////////////////////////////////////////////////////////////////////////
   //disable_interrupts(INT_TIMER1);
   cola[1].estado=2;
   TMR1IF=0;     //flag de interrupcion 0
   cola[np+1]=cola[1];
   for (j=1; j<=np+1;j++){
      cola[j]=cola[j+1];
   }          
   if(calendarizacion=1) 
   {enable_interrupts(INT_TIMER0);
   }
   goto_address(proceso[0].di); 
   }
}
#INT_TIMER0
void Reloj_interno_SO(){
set_timer0(0xD8EF);
 if(u1==y[0]||u2==y[1]||u3==y[2])
   {  
               if(u1==y[0]){u1=1;cp=1;minus=0;}
               if(u2==y[1]){u2=1;cp=2;minus=0;}
               if(u3==y[2]){u3=1;cp=3;minus=0;}
               if(calendarizacion)
               {proceso[cp].estadoc=0;}
               proceso[cp].estado=0;
               for (i=1;i<=npc;i++)
               {
                  if(colart[i].id==proceso[cp].id) colart[i].estadoc=0;
               }
               for (i=1;i<=np;i++)
               {  
                  
                  if (cola[i].id==proceso[cp].id)
                  {
                     for (j=i;j<=np;j++)
                        {
                        colart[j]=colart[j+1];
                        }
                     np--;
                     i=np+1;
                  }               
               }
               npc--;
               }
  
for(i=1;i<=npc;i++) 
{if(colart[i].estadoc) colart[i].timer++;
}
TMR0IF=0;
}
void MCU_Init(void)
{
   enable_interrupts(GLOBAL);
   TRISB=0x00;
   PORTB=0x00;
   TRISA=0x00;
   PORTA=0x00;
   set_timer1(0x200);
   setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_2 );
   set_timer0(0xD8EF);
   setup_timer_0 ( RTCC_DIV_1);
   enable_interrupts(INT_TIMER0);
}

void main ()
{  MCU_Init();
//S.O
   proceso[0].id=0;
   proceso[0].di=0x0886;
   proceso[0].estado=1;
//PROCESO 1
   proceso[1].id=1;
   proceso[1].di=0x1200;
   proceso[1].estado=0;
   proceso[1].muestreo=500;
   proceso[1].pila=0;
   proceso[1].estadoc=0;
//PROCESO 2
   proceso[2].id=2;
   proceso[2].di=0x1400;
   proceso[2].estado=0;
   proceso[2].muestreo=100;
   proceso[2].pila=3;
   proceso[2].estadoc=0;
//PROCESO 3
   proceso[3].id=3;
   proceso[3].di=0x1600;
   proceso[3].estado=0;
   proceso[3].muestreo=300;
   proceso[3].pila=7;
   proceso[3].estadoc=0;
//PROCESO 4 
   proceso[4].id=4; 
   proceso[4].di=0x1800;
   proceso[4].estado=0;
   proceso[4].muestreo=800;
   proceso[4].pila=12;
   proceso[4].estadoc=0;
//Dirección 0x0180
   while (true)
   {
   if(kbhit()==1)
   {dato=getc();
   buffer[r]=dato;
   r++;
   /*if(dato=='1')
      cp=dato-0x30;//para arreglar el cp al numero de proceso 1
      if(dato=='2')
      cp=dato-0x30;
      if(dato=='3')
      cp=dato-0x30;*///para arreglar el cp al numero de proceso 2
      switch (dato)
         {
            case 'x':   cp=1;
                  buffer[0]=0;
                  r=0;
                  break;
            case 'y':   cp=2;
                  buffer[0]=0;
                  r=0;
                  break;
            case 'z':   cp=3;
                  buffer[0]=0;
                  r=0;
                  break;
            case '-':   minus[cp-1]=1;
                  r=0;
                  break;
            case 'U':   proceso[cp].muestreo=100;
                  break;
            case 'I':   proceso[cp].muestreo=400;
                  break;
            case 'O':   proceso[cp].muestreo=1000;
                  break;   
            case 'm':            // CARGAR PROCESO
               y[cp-1]=8*atoi(buffer);
               mayor=y[0];
               for(ma=0;ma<=2;ma++)
               {if(y[ma]>mayor)
               {mayor=y[ma];}
               }
               for(ma=0;ma<=2;ma++)
               {if(y[ma]==0)factor[ma]=0;
               else {factor[ma]=mayor/y[ma];}
               proceso[ma+1].muestreo=10*factor[ma];}
               if(calendarizacion)
               {npc++;}
               else 
               {np++;
               }
               proceso[cp].estado=0;
               proceso[cp].estadoc=calendarizacion;
               if(calendarizacion) colart[npc]=proceso[cp];
               else cola[np]=proceso[cp];
                for(z=0;z<=r;z++)
               {buffer[z]=0;}
               r=0;
               break;
            default:    break;}           
         
   }
      if((calendarizacion==1)&&(npc>0)){
         disable_interrupts(INT_TIMER1);
         enable_interrupts(GLOBAL);
         enable_interrupts(INT_TIMER0);
         for(m=1;m<=npc;m++){
         if(colart[m].muestreo<=colart[m].timer) 
         {
         colart[m].timer=0;
         colart[m].estado=1;
         np++;
         cola[np]=colart[m];
         }
      }
      }
      if(np>0)
      {
         if(cola[1].estado==1)
            {//inicia quantum//
            STKPTR=cola[1].pila;
            enable_interrupts(GLOBAL);
            TMR1IF=0;         
            set_timer1(0x200);
            enable_interrupts(INT_TIMER1);
            ////////////////////            
            goto_address(cola[1].di);
            }
         if(cola[1].estado==2)
            {
            STKPTR=cola[1].pila;
            enable_interrupts(GLOBAL);
            TMR1IF=0;
            set_timer1(0x200);
            enable_interrupts(INT_TIMER1);
            WREG=cola[1].w;
            STATUS=cola[1].status;
            BSR=cola[1].bsr;
            goto_address(cola[1].da);
            /* #ASM
            RETURN
            #ENDASM*/ 
            }
      } 
   }
}

